//
//  ZYPurchaseSaleman.h
//  ZYPurchase
//
//  Created by wu on 2020/8/6.
//  Copyright © 2020 wu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ZYPurchaseDelegate.h"
#import "ZYPurchaseTransactionModel.h"

#import <StoreKit/StoreKit.h>
#import <AFNetworking/AFNetworkReachabilityManager.h>

FOUNDATION_EXPORT NSString *const ZYPurchaseAPI_CreateOrder;        // 创建订单
FOUNDATION_EXPORT NSString *const ZYPurchaseAPI_PayFailure;         // 支付失败
FOUNDATION_EXPORT NSString *const ZYPurchaseAPI_VerifyReceipt;      // 收据校验
FOUNDATION_EXPORT NSString *const ZYPurchaseAPI_Get_SubscribeStatus;      // 查询订阅状态

@class ZYPurchaseDataBase;
@class ZYProductsRequest;
@class SKReceiptRefreshRequest;
@class SKProductsRequest;

/**
 使用流程：
 第一步：创建订单；
 第二步：发起支付；
 第三步：根据回调的支付结果，处理订单后续状态（如发放虚拟物品、或发货）
 
 
 关于创建订单时的商品信息数组 productInfo 必须存放商品信息，且所有商品必须可以使用同一种支付类型
 
 
 Note:
 售货员是 “单线程” 方式交易方式，同一时刻只会处理一个交易，且在售货员处理订单期间发起的交易会放在 waitingQueue 队列等待
 
 */

NS_ASSUME_NONNULL_BEGIN


/**
 用户设备(当前手机) IAP Restore 状态有三种， 未访问过、加载中、访问过
 
 未访问过：此设备从未点击过购买IAP商品
 加载中：第一次点击IAP商品时，尝试 restore 当前 Apple ID 下已订阅内容到设备上
 访问过：这种状态会在启动时直接 restore
 
 疑问：为什么多加这个状态，在启动时直接restore当前设备的内购状态不可以？
 （前置条件：实践发现，每个设备第一次调用restore时会弹窗提示用户输入Apple ID的密码，系统控件无法避免）
 若启动时restore会有如下情况发生，在设备安装App后的第一次启动App后，会弹窗提示用户输入当前设备的Apple ID和密码，为了避免用户产生隐私泄露的担忧，
 因此在第一次使用IAP服务时restore是很有必要的，因此目前逻辑时，若用户从未使用过IAP，则是默认状态 NotAccessed，当用户第一次点击内购商品时，会进入Asking状态，询问此Apple ID用户的内购订阅情况，
 当获取到内购数据时，置为Accessed状态
 */

typedef NS_ENUM(NSInteger, ZYPurchaseIAPRestoreStatus) {
    ZYPurchaseIAPRestoreStatus_NotAccessed = 0,      // 此设备从未使用过IAP，未访问过IAP信息
    ZYPurchaseIAPRestoreStatus_Asking,               // 询问中
    ZYPurchaseIAPRestoreStatus_Accessed,             // 已经访问过
    ZYPurchaseIAPRestoreStatus_AccessedFail,             // 查询失败
};


FOUNDATION_EXPORT NSString *const ZYPurchaseCreateOrderComplete_Notifi;         // 创建订单结果的通知
FOUNDATION_EXPORT NSString *const ZYPurchaseTransactionStatusChanged_Notifi;    // 交易状态变更的通知
FOUNDATION_EXPORT NSString *const ZYPurchasePurchasedWithoutTransaction_Notifi;    // 支付结束但没找到交易的通知
// 获取国家码用的商品id  ， 用一定存在的商品id即可
FOUNDATION_EXPORT NSString *const ZYPurchase_CountryCodeRequest_ProductId;

@interface ZYPurchaseSaleman : NSObject

@property (nonatomic, assign) AFNetworkReachabilityStatus reachabilityStatus;

// 交易等待队列
//@property (nonatomic, readonly) NSArray <ZYPurchaseTransactionModel *>*waitingQueue;
// 交易代理
@property (nonatomic, weak) id <ZYPurchaseTransactionDelegate> transaction_delegate;
// 订单代理
@property (nonatomic, weak) id <ZYPurchaseOrderDelegate> order_delegate;

// 智云服务器地址（处理支付订单相关）
@property (nonatomic, copy) NSString *serverHost;

// 再次校验收据中的订单id （请仅用于再次校验逻辑）
@property (nonatomic, copy, nullable) NSString *reVerifyOrderId;

/////////////   Private property

/// 用于请求获取商品价格的商品列表（供h5展示）
@property (nonatomic, strong, nullable) ZYProductsRequest *priceRequest;
@property (nonatomic, copy, nullable) void (^ priceRequestHandler)(BOOL success, id info);
@property (nonatomic, copy, nullable) void (^ invalidProductIdentifiers)(id invalidArray);

/**
 // 交易等待队列
 @property (nonatomic, strong, readwrite) NSMutableArray <ZYPurchaseTransactionModel *>*waitingQueue;
 */
// 购买的产品数组
@property (nonatomic, copy) NSArray *products;
// 发起购买的用户id
@property (nonatomic, copy) NSString *customerId;
// 发起购买的用户token
@property (nonatomic, copy) NSString *customerToken;
// 设备唯一标识符
@property (nonatomic, copy) NSString *deviceUUID;
// 国家码
@property (nonatomic, copy) NSString *countryCode;

//@property (nonatomic, strong) FBKVOController *fbObserver;

/// IAP 访问状态
@property (nonatomic, assign) ZYPurchaseIAPRestoreStatus restoreStatus;

/// 当前处理中的交易
@property (nonatomic, strong) ZYPurchaseTransactionModel *currentTransaction;



@property (nonatomic, strong) ZYPurchaseDataBase *database;
//
@property (nonatomic, strong) SKReceiptRefreshRequest *receiptRequest;

@property (nonatomic, copy) void(^ requestReceiptBlock)(BOOL success, id info);

// 发起支付时的回调，主要用于回调订单信息
@property (nonatomic, copy) void(^ createOrderBlock)(BOOL success, id info);

/////////////

/// 判断是否是订阅产品标识
+ (BOOL)isSubscribe:(nonnull NSString *)productIdentifier;

/// 获取订阅状态（在智云平台的）
+ (void)getCurrentUserSubscribeStatus:(void(^)(BOOL success, id info))complete;

// 查询 IAP 数据
+ (void)restoreIAPPurchaseInfo;
/// 是否访问过IAP数据
+ (BOOL)restoreStatusAccessed;

/// 添加或更新 log 记录
+ (void)resetLogRecorder;
/// 结束一次log记录
+ (BOOL)finishLogRecord;
/// 记录log
+ (void)logRecord:(id)content;
- (void)logRecord:(id)content;
- (void(^)(id content))logRecord;

/// 创建订单信息
/// @param productInfo 产品信息
/// @param isDigital 是否是虚拟商品准备走内购
/// @param complete 创建订单结果回调，成功时info是 ZYPurchaseOrderModel 实例，失败时是出错原因
+ (void)createOrder:(nonnull NSArray <NSDictionary *>*)productInfo
          isDigital:(BOOL)isDigital
           complete:(nonnull void (^)(BOOL success, id info))complete;


/// 开始支付
/// @param orderInfo 订单信息
/// @param paymentMethod 支付方式
/// @param customerId 用户id
//+ (void)startPayment:(ZYPurchaseOrderModel *)orderInfo
//       paymentMethod:(ZYPurchasePaymentMethod)paymentMethod
//          customerId:(nonnull NSString *)customerId;

/// 单例
+ (instancetype)defaultSaleman;

/// 支付方式是否支持
+ (BOOL)supportPaymentMethod:(ZYPurchasePaymentMethod)paymentMethod;


/// 重置服务器地址
+ (void)resetPurchaseHost:(nonnull NSString *)host;

// 格式化支付url
+ (NSString *(^)(NSString *path))formatPurchageUrlString;

/// 重置客户信息
/// @param customerId 用户 id
/// @param customerToken 用户 token
+ (void)resetCustomerInfo:(nonnull NSString *)customerId
            customerToken:(nonnull NSString *)customerToken;


/// 设置设备唯一标识符
/// @param uuid uuid
+ (void)setupDeviceUUID:(NSString *)uuid;

+ (NSDictionary *(^)(NSInteger errorCode))formatErrorResponse;

/// 请求国家码
+ (void)requestCountryCodeIfNeeded:(nullable void (^)(NSString *countryCode))complete;
@property (nonatomic, copy, nullable) void (^ countryCodeRequestBlock)(NSString *countryCode);


@end


@interface NSString (ZYPurchageExtension)
// 是否可用
- (BOOL)zy_isValuable;
@end

@interface NSDictionary (ZYPurchageSafety)

/**
 获取字符串
 */
- (NSString *)zy_stringForKey:(NSString *)key;

@end

@interface ZYProductsRequest : SKProductsRequest

// 是否是用于查询价格
@property (nonatomic, assign) BOOL isPriceRequest;

@property (nonatomic, strong) NSArray *productsIdArray;

@property (nonatomic, strong) NSMutableArray *productsInfo;

@end

NS_ASSUME_NONNULL_END
